﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using CloudShot.Core.Interfaces;
using CloudShot.Utils;

namespace CloudShot.Services
{
	class PluginManager
	{
		private readonly string _pluginsRoot;
		public string PluginsRoot { get { return _pluginsRoot; } }

		public PluginManager(string pluginsRoot)
		{
			_pluginsRoot = pluginsRoot;
			AppDomain.CurrentDomain.AssemblyResolve += OnAssemblyResolve;
		}

		public IEnumerable<IImageStorage> GetPlugins()
		{
			if (!Directory.Exists(_pluginsRoot))
				yield break;

			string[] directories = Directory.GetDirectories(_pluginsRoot);
			var assemblies = new List<Assembly>();

			foreach (string directory in directories)
			{
				string[] files = Directory.GetFiles(directory, "*.dll", SearchOption.TopDirectoryOnly);

				foreach (string file in files)
				{
					Assembly assembly;

					if (TryLoadAssembly(file, out assembly))
						assemblies.Add(assembly);
				}
			}

			foreach (var assembly in assemblies)
			{
				IEnumerable<Type> storageTypes = assembly.FindDerivedTypesFromAssembly(typeof(IImageStorage));

				foreach (Type storageType in storageTypes)
				{
					IImageStorage storage = Activator.CreateInstance(storageType) as IImageStorage;
					yield return storage;
				}
			}
		}

		public bool InstallPlugin(string filename)
		{
			return false;
		}

		private bool TryLoadAssembly(string fileName, out Assembly assembly)
		{
			try
			{
				assembly = Assembly.LoadFile(fileName);
				return true;
			}
			catch
			{
				assembly = null;
				return false;
			}
		}

		private Assembly OnAssemblyResolve(object sender, ResolveEventArgs args)
		{
			Assembly assembly = null;
			Assembly[] myAssemblies = AppDomain.CurrentDomain.GetAssemblies();

			foreach (Assembly myAssembly in myAssemblies)
			{
				if (args.Name == myAssembly.FullName)
				{
					assembly = myAssembly;
					break;
				}
			}

			return assembly;
		}
	}
}